package pay

import (
	"context"
	"encoding/json"
	"strings"
	"time"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
)

type DaxingPay struct{}

var (
	User                  = "aotosell"   // 请求用户 测试收银员 10312001
	SellerID              = "BDIA_ACT"   // 收款账户
	MallID                = "000001"     // 商场号
	StoreCode             = "xingliyu01" // 店铺号 111000
	BsStoreCode           = "xingliyu01" // 合同店铺号(未使用到则直接填写为店铺号) 111000
	TillID                = 02           // 测试信息
	ApiKey                = "w5NCFC84OVXh"
	COMMON_URL            = "https://pay.bdia.com.cn/cros_svc.aspx"
	CREATE_ORDER_URL      = COMMON_URL + "?method=precreate"
	REFUND_ORDER_URL      = COMMON_URL + "?method=refund"
	QUERY_ORDER_URL       = COMMON_URL + "?method=orderquery"
	UPLOAD_SALES_INFO_URL = "http://xscjsm.bdia.com.cn:8195/web63/rest/salestransaction/salestranslitev61"
)

func (dx DaxingPay) DaxingInit(user, sellerID, mallID, storeCode, bsStoreCode, apiKey string) {
	if user != "" {
		User = user
	}
	if sellerID != "" {
		SellerID = sellerID
	}
	if mallID != "" {
		MallID = mallID
	}
	if storeCode != "" {
		StoreCode = storeCode
	}
	if bsStoreCode != "" {
		BsStoreCode = bsStoreCode
	}
	if apiKey != "" {
		ApiKey = apiKey
	}
}

type DaxingHeader struct {
	ErrorCode    string `json:"ErrorCode"`    // "0"
	ErrorMSG     string `json:"ErrorMSG"`     // ""
	ResObj       string `json:"ResObj"`       // ""
	CRC          string `json:"CRC"`          // "DEF20230517092940183"
	Alert        string `json:"Alert"`        // ""
	PostObj      string `json:"PostObj"`      // ""
	ResDateTime  string `json:"ResDateTime"`  // "2023/5/17 9:29:40 497"
	PayTypeCode  string `json:"PayTypeCode"`  // "WX"
	PayTypeDesci string `json:"PayTypeDesci"` // ""
	ProcessTime  string `json:"ProcessTime"`  // 313
}
type CreateOrderRsp struct {
	Header DaxingHeader `json:"Header"`
	Result struct {
		OutID     string      `json:"OutID"`     //"1684286975038476",
		QRCode    string      `json:"QRCode"`    //"d2VpeGluOi8vd3hwYXkvYml6cGF5dXJsP3ByPTlxT3BOVG96eg==",
		PicUrl    string      `json:"PicUrl"`    //"d2VpeGluOi8vd3hwYXkvYml6cGF5dXJsP3ByPTlxT3BOVG96eg==",
		ExtResult interface{} `json:"ExtResult"` //null
	} `json:"Result"`
}

type QueryOrderRsp struct {
	Header DaxingHeader `json:"Header"`
	Result struct {
		SN            string `json:"SN"`
		TotalFee      string `json:"TotalFee"`      //1
		ActualFee     string `json:"ActualFee"`     //1
		CouponFee     string `json:"CouponFee"`     //0
		TradeNO       string `json:"TradeNO"`       //"2023051722001456061454333815"
		OutID         string `json:"OutID"`         // "1684309847602929",
		BuyerID       string `json:"BuyerID"`       //"2088502919256063"
		RefundOutID   string `json:"RefundOutID"`   // ""
		RefundTradeNO string `json:"RefundTradeNO"` //""
		TXType        string `json:"TXType"`        // "SA"
		Status        string `json:"Status"`        // "30"
		TXdate        string `json:"TXdate"`        // "2023-05-17"
		OfficialDate  string `json:"OfficialDate"`  // "20230517155053"
		ExtResult     string `json:"ExtResult"`     // ""
		//eyJQYXltZW50RGV0YWlsIjpbeyJDaGFubmVsIjoiVDQyIiwiRmVlIjoiMSIsIlBheW1lbnRDb2RlIjoiQUxJUEFZQUNDT1VOVCIsIk5hbWUiOiLmlK/ku5jlrp3kvZnpop0ifV0sIlZvdWNoZXJUeXBlIjoiIn0=
		//ExtResult 解析base64结果为 {"PaymentDetail":[{"Channel":"T42","Fee":"1","PaymentCode":"ALIPAYACCOUNT","Name":"支付宝余额"}],"VoucherType":""}
		DiscountAmt string `json:"DiscountAmt"` // "0"
		OrgCRC      string `json:"OrgCRC"`      // "DEF20230517155053240"
		PayTypeCode string `json:"PayTypeCode"`
		PayStore    string `json:"PayStore"`
		SalesDocNo  string `json:"SalesDocNo"`
	} `json:"Result"`
}

// CreateOrder 订单创建
// !!! TotalFee 金额 (单位:分)
func (dx DaxingPay) CreateOrder(ctx context.Context, PayType, OutID string, TotalFee float64, Remark string) (Rsp CreateOrderRsp, err error) {
	var Header = make(map[string]string)
	var Params = make(map[string]interface{})
	Params["Header"] = map[string]interface{}{
		"TerminalType": "1",                             // 0    Pos终端， 1平板
		"TXDate":       time.Now().Format("2006-01-02"), // 固定参数
		"MallID":       MallID,                          // 固定参数
		"StoreCode":    StoreCode,                       // 非固定，需配置
		"BSStoreCode":  BsStoreCode,                     // 非固定，需配置
		"TillID":       01,                              // 固定
		"CashierNO":    User,                            // 固定
		"CRC":          "",                              // 固定默认为空
		"Type":         PayType,
		"Key":          ApiKey,
		"SellerID":     SellerID,
		"ExtParam":     "",
	}
	Params["RequestParam"] = map[string]interface{}{
		"OutID":    OutID,
		"TotalFee": TotalFee,
		"Subject":  "",
	}
	statusCode, Response, err := helper.Net{}.Request(ctx, "POST", CREATE_ORDER_URL, Header, Params)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "daxingpay create order err", logx.Any("err", err.Error()))
		err = errorx.New("大兴支付创建订单失败", -1)
		return
	}
	var CreateOrderRsp CreateOrderRsp
	json.Unmarshal(Response, &CreateOrderRsp)
	return CreateOrderRsp, nil
}

// QueryOrder 订单查询
// !!! TotalFee 金额(单位:分)
func (dx DaxingPay) QueryOrder(ctx context.Context, PayType, outTradeNo string, TotalFee float64) (Rsp QueryOrderRsp, err error) {
	var Header = make(map[string]string)
	var Params = make(map[string]interface{})
	Params["Header"] = map[string]interface{}{
		"TerminalType": "1",         // 0    Pos终端， 1平板
		"TXDate":       "",          // 固定参数
		"MallID":       MallID,      // 固定参数
		"StoreCode":    StoreCode,   // 非固定，需配置
		"BSStoreCode":  BsStoreCode, // 非固定，需配置
		"TillID":       01,          // 固定
		"CashierNO":    User,        // 固定
		"CRC":          "",          // 固定默认为空
		"Type":         PayType,
		"Key":          ApiKey,
		"SellerID":     SellerID,
		"ExtParam":     "",
	}
	Params["RequestParam"] = map[string]interface{}{
		"OutID":    outTradeNo,
		"TotalFee": TotalFee,
		"Subject":  "",
	}
	statusCode, Response, err := helper.Net{}.Request(ctx, "POST", QUERY_ORDER_URL, Header, Params)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "daxingpay create order err", logx.Any("err", err.Error()))
		err = errorx.New("大兴支付查询订单失败", -1)
		return
	}
	var QueryOrderResponse QueryOrderRsp
	json.Unmarshal(Response, &QueryOrderResponse)
	return QueryOrderResponse, nil
}

// UpSales 上传销售数据 [todo:返回值Result没有验证]
func (dx DaxingPay) UpSales(ctx context.Context, outTradeNo string, GoodsNum int, TotalFee float64, GoodsCode, tenderCode string) (Rsp QueryOrderRsp, err error) {
	var Header = make(map[string]string)
	transHeader := map[string]interface{}{
		"txDate":         time.Now().Format("2006-01-02"),
		"ledgerDatetime": time.Now().Format("2006-01-02 15:04:05"),
		"storeCode":      StoreCode,
		"tillId":         "02",
		"docNo":          outTradeNo,
	}
	salesTotal := map[string]interface{}{
		"cashier":         User,
		"vipCode":         "",
		"netQty":          GoodsNum,
		"netAmount":       TotalFee / 100,
		"extendParameter": "",
	}
	salesItem := map[string]interface{}{
		"salesLineNumber":   1,
		"vipBonusEarn":      0,
		"vipBonusRedeem":    0,
		"itemCode":          GoodsCode,
		"itemLotNum":        "*",
		"inventoryType":     0,
		"qty":               GoodsNum,
		"originalPrice":     0,
		"itemDiscountLess":  0,
		"totalDiscountLess": 0,
		"netAmount":         TotalFee / 100,
		"salesItemRemark":   "",
		"extendParameter":   "",
		"promotionResult":   "",
	}
	salesTender := map[string]interface{}{
		"baseCurrencyCode": "RMB",
		"tenderCode":       tenderCode, // 支付方式：目前支持2种: AP 支付宝(alipay) WP	微信 (wechatpay
		"tenderType":       "0",
		"payAmount":        TotalFee / 100, // 付款金额
		"baseAmount":       TotalFee / 100, // 本位币付款金额
		"excessAmount":     0,
		"lineno":           0,
		"extendParameter":  "",
	}
	var Params = make(map[string]interface{})
	Params["apiKey"] = "STANDARD"
	Params["transHeader"] = transHeader
	Params["salesTotal"] = salesTotal
	Params["salesItem"] = salesItem
	Params["salesTender"] = salesTender
	Params["salesMobilePayments"] = []string{}
	Params["docKey"] = "20181127.2409.15" + outTradeNo
	statusCode, Response, err := helper.Net{}.Request(ctx, "POST", UPLOAD_SALES_INFO_URL, Header, Params)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "daxingpay up_sales_info err", logx.Any("err", err.Error()))
		err = errorx.New("大兴支付失败", -1)
		return
	}
	logx.Info(ctx, "daxingpay up_sales_info info", logx.Any("resp", Response))
	var QueryOrderResponse QueryOrderRsp
	json.Unmarshal(Response, &QueryOrderResponse)
	return QueryOrderResponse, nil
}

type RefundResponse struct {
	Header DaxingHeader `json:"Header"`
	Result struct {
		SN            string `json:"SN"`
		TotalFee      string `json:"TotalFee"`
		ActualFee     string `json:"ActualFee"`
		CouponFee     string `json:"CouponFee"`
		TradeNO       string `json:"TradeNO"`
		OutID         string `json:"OutID"`
		BuyerID       string `json:"BuyerID"`
		RefundOutID   string `json:"RefundOutID"`
		RefundTradeNO string `json:"RefundTradeNO"`
		TXType        string `json:"TXType"`
		Status        string `json:"Status"`
		TXdate        string `json:"TXdate"`
		OfficialDate  string `json:"OfficialDate"`
		ExtResult     string `json:"ExtResult"`
		DiscountAmt   string `json:"DiscountAmt"`
		OrgCRC        string `json:"OrgCRC"`
		PayTypeCode   string `json:"PayTypeCode"`
		PayStore      string `json:"PayStore"`
		SalesDocNo    string `json:"SalesDocNo"`
	} `json:"Result"`
}

// Refund 订单退款
// !!! TotalFee 金额(单位:分) [todo:返回值Result没有验证]
func (dx DaxingPay) Refund(ctx context.Context, outTradeNo, PayType string, TotalFee float64) (res RefundResponse, err error) {
	var Header = make(map[string]string)
	var Params = make(map[string]interface{})
	Params["Header"] = map[string]interface{}{
		"TerminalType": "1",         // 0    Pos终端， 1平板
		"TXDate":       "",          // 固定参数
		"MallID":       MallID,      // 固定参数
		"StoreCode":    StoreCode,   // 非固定，需配置
		"BSStoreCode":  BsStoreCode, // 非固定，需配置
		"TillID":       01,          // 固定
		"CashierNO":    User,        // 固定
		"CRC":          "",          // 固定默认为空
		"Type":         PayType,
		"Key":          ApiKey,
		"SellerID":     SellerID,
		"ExtParam":     "",
	}
	Params["RequestParam"] = map[string]interface{}{
		"OutID":          outTradeNo,
		"RefundAmount":   TotalFee,
		"OriginalTXDate": "", //隔日退款传此处参数: time.Now().Add(-48 * time.Hour).Format("2006-01-02"),
		"TotalFee":       TotalFee,
		"DynamicID":      "",
	}
	statusCode, Response, err := helper.Net{}.Request(ctx, "POST", REFUND_ORDER_URL, Header, Params)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "daxingpay refund order err", logx.Any("err", err.Error()))
		err = errorx.New("大兴订单退款失败", -1)
		return
	}
	var RefundResponse RefundResponse
	json.Unmarshal(Response, &RefundResponse)
	return RefundResponse, nil
}

// UpSalesRefund 回退商品销售数据
func (dx DaxingPay) UpSalesRefund(ctx context.Context, outTradeNo string, GoodsNum int, TotalFee float64, GoodsCode, tenderCode string) (Rsp QueryOrderRsp, err error) {
	var Header = make(map[string]string)
	transHeader := map[string]interface{}{
		"txDate":         time.Now().Format("2006-01-02"),
		"ledgerDatetime": time.Now().Format("2006-01-02 15:04:05"),
		"storeCode":      StoreCode,
		"tillId":         "02",
		"docNo":          outTradeNo,
	}
	salesTotal := map[string]interface{}{
		"cashier":         User,
		"vipCode":         "",
		"netQty":          -GoodsNum,
		"netAmount":       -(TotalFee / 100),
		"extendParameter": "",
	}
	salesItem := map[string]interface{}{
		"salesLineNumber":   1,
		"vipBonusEarn":      0,
		"vipBonusRedeem":    0,
		"itemCode":          GoodsCode,
		"itemLotNum":        "*",
		"inventoryType":     0,
		"qty":               -GoodsNum,
		"originalPrice":     0,
		"itemDiscountLess":  0,
		"totalDiscountLess": 0,
		"netAmount":         -(TotalFee / 100),
		"salesItemRemark":   "",
		"extendParameter":   "",
		"promotionResult":   "",
	}
	salesTender := map[string]interface{}{
		"baseCurrencyCode": "RMB",
		"tenderCode":       tenderCode, // 支付方式：目前支持2种: AP 支付宝(alipay) WP	微信 (wechatpay
		"tenderType":       "0",
		"payAmount":        -(TotalFee / 100), // 付款金额
		"baseAmount":       -(TotalFee / 100), // 本位币付款金额
		"excessAmount":     0,
		"lineno":           0,
		"extendParameter":  "",
	}
	var Params = make(map[string]interface{})
	Params["apiKey"] = "STANDARD"
	Params["transHeader"] = transHeader
	Params["salesTotal"] = salesTotal
	Params["salesItem"] = salesItem
	Params["salesTender"] = salesTender
	Params["salesMobilePayments"] = []string{}
	Params["docKey"] = "20181127.2409.15" + outTradeNo
	Params["orgSalesMemo[]"] = strings.Split(outTradeNo, "_")[0]
	statusCode, Response, err := helper.Net{}.Request(ctx, "POST", UPLOAD_SALES_INFO_URL, Header, Params)
	if statusCode != 200 || err != nil {
		logx.Error(ctx, "daxingpay up_sales_info refund err", logx.Any("err", err.Error()))
		err = errorx.New("大兴发送销售信息失败", -1)
		return
	}
	logx.Info(ctx, "daxingpay up_sales_info refund info", logx.Any("resp", Response))
	var QueryOrderResponse QueryOrderRsp
	json.Unmarshal(Response, &QueryOrderResponse)
	return QueryOrderResponse, nil
}
